package com.bbva.kyfb.kyfbutils.constantes;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.bbva.jee.arq.spring.core.gce.CodigoError;
import com.bbva.jee.arq.spring.core.gce.ExcepcionEjecucionAplicacion;

/**
 * The Class Util.
 */
public class UtilFO
{

	/** The fecha proceso. */
	public static final String FECHA_PROCESO= "FP";

	/** The fecha creacion. */
	public static final String FECHA_CREACION= "FC";

	/** The est pdte firma. */
	public static final String EST_PDTE_FIRMA = "PF";

	/** The est fdo parcial. */
	public static final String EST_FDO_PARCIAL = "FP";

	/** The est pdte auditor. */
	public static final String EST_PDTE_AUDITOR = "PA";

	/** The est firmado. */
	public static final String EST_FIRMADO = "PE";

	/** The est env asistente. */
	public static final String EST_ENV_ASISTENTE = "FF";

	/** The est firmado enviado. */
	public static final String EST_FIRMADO_ENVIADO = "HO";

	/** The est eliminado usuario. */
	public static final String EST_ELIMINADO_USUARIO = "EL";

	/** The perfil activo. */
	public static final String PERFIL_ACTIVO = "A";

	/** The ordenante beneficiario. */
	public static final String ORDENANTE_BENEFICIARIO="O";

	/** The usuario apoderado. */
	public static final String USUARIO_APODERADO = "P";

	/** The usuario auditor. */
	public static final String USUARIO_AUDITOR = "A";

	/** The usuario bbdd tlbh. */
	public static final String USUARIO_BBDD_TLBH = "VAR.DATABASE.USERNAME_TLBH";

	/** The usuario bbdd tlsb. */
	public static final String USUARIO_BBDD_TLSB = "VAR.DATABASE.USERNAME_TLSB";

	/** The xsn firmado. */
	public static final char XSN_FIRMADO = 'S';

	/** The xsn firmado. */
	public static final char XSN_FIRMADO_N = 'N';

	/** The asistente ok. */
	public static final String ASISTENTE_OK = "ASI0100000";

	/** The borrado. */
	public static final short BORRADO = 8;

	/** The borrado int. */
	public static final Integer BORRADO_INT = 0;

	/** Poderes de firma. */
	public static final String FIRMA_SOLIDARIO = "S";

	/** The FIRM a_ mancomunad o2. */
	public static final String FIRMA_MANCOMUNADO2 = "M2";

	/** The FIRM a_ mancomunad o3. */
	public static final String FIRMA_MANCOMUNADO3 = "M3";

	/** The FIRM a_ mancomunad o4. */
	public static final String FIRMA_MANCOMUNADO4 = "M4";

	/** The poder firma solidario. */
	public static final double PODER_FIRMA_SOLIDARIO = 1;

	/** The PODE r_ firm a_ mancomunad o2. */
	public static final double PODER_FIRMA_MANCOMUNADO2 = 0.5;

	/** The PODE r_ firm a_ mancomunad o3. */
	public static final double PODER_FIRMA_MANCOMUNADO3 = 0.34;

	/** The PODE r_ firm a_ mancomunad o4. */
	public static final double PODER_FIRMA_MANCOMUNADO4 = 0.25;

	/** The estados todos. */
	public static final String ESTADOS_TODOS = "TO";

	/** Longitud que debe tener el numero aleatorio generado (9) */
	public static final int LONGITUD_NUM_ALEATORIO = 9;

	/** Mapa de estados */
	private static final Map<String,String> MAP_ESTADO_COD = new HashMap<String,String>();

	/** Mapa de destados por intenger */
	private static final Map<String,String> MAP_COD_ESTADO = new HashMap<String,String>();

	/** Mapa de acciones por codigo */
	private static final Map<Integer,String> MAP_COD_ACCION = new HashMap<Integer,String>();

	/** The zona euro. */
	private static final List<String> LST_ZONA_EURO = new ArrayList<String>();

	/**The estados host pendiente*/
	private static List<String> estadosHostPendiente = new ArrayList<String>(Arrays.asList("0050", "0055"));
	
	/**The estados posibles host*/
	private static final List<String> estadosHost = Arrays.asList("0010", "0011", "0012", "0013", "0014", "0015", "0016", 
																 "0017", "0018", "0019", "0020", "0021", "0022", "0023", 
																 "0024", "0025", "0026", "0027", "0028", "0029", "0030", 
																 "0031", "0032", "0033", "0034", "0035", "0036", "0037", 
																 "0038", "0039", "0040", "0041", "0042", "0043", "0044", 
																 "0045", "0046", "0047", "0048", "0049", "0050", "0051", 
																 "0052", "0053", "0054", "0055", "0058", "0062", "0063", 
																 "0064", "0065", "0066", "0069", "0070", "0071", "0072", 
																 "0074", "0075", "0076", "0077", "0078", "0090", "0091", 
																 "0095", "0097", "0098", "0099", "0100", "0200");
	/** Clases internacionales. */
	private static final List<String> LST_CLASE_INTERNACIONAL = new ArrayList<String>();
	
	/** Mapa de clases de red exterior */
	private static final Map<String,String> MAP_CLASE_RED_EXTERIOR = new HashMap<String,String>();
	
	static {

		// Seteamos los posibles valores de los estados.
		MAP_ESTADO_COD.put("EC","001");
		MAP_ESTADO_COD.put("PN","003");
		//MAP_ESTADO_COD.put("PN","002"); Se queda el prioritario
		MAP_ESTADO_COD.put("EN","004");
		MAP_ESTADO_COD.put("EX","006");
		MAP_ESTADO_COD.put("PD","011");
		MAP_ESTADO_COD.put("PL","016");
		MAP_ESTADO_COD.put("PX","017");
		MAP_ESTADO_COD.put("LI","018");
		MAP_ESTADO_COD.put("FP","019");
		MAP_ESTADO_COD.put("PA","020");
		MAP_ESTADO_COD.put("PE","021");
		MAP_ESTADO_COD.put("HO","022");
		MAP_ESTADO_COD.put("RE","023");
		MAP_ESTADO_COD.put("PF","024");
		MAP_ESTADO_COD.put("EJ","025");
		MAP_ESTADO_COD.put("RF","026");
		MAP_ESTADO_COD.put("EP","027");
		MAP_ESTADO_COD.put("PR","028");
		MAP_ESTADO_COD.put("ER","029");
		MAP_ESTADO_COD.put("PC","030");
		MAP_ESTADO_COD.put("PP","031");
		MAP_ESTADO_COD.put("RA","032");
		MAP_ESTADO_COD.put("FF","696");
		MAP_ESTADO_COD.put("AT","994");
		MAP_ESTADO_COD.put("BM","995");
		MAP_ESTADO_COD.put("BH","996");
		MAP_ESTADO_COD.put("BD","997");
		//MAP_ESTADO_COD.put("BD","998"); Se queda el prioritario
		MAP_ESTADO_COD.put("EL","999");

		// Invertimos el hashmap para la búsqueda contraria
		for(final Entry<String, String> ent:MAP_ESTADO_COD.entrySet()){
			MAP_COD_ESTADO.put(ent.getValue(), ent.getKey());
		}
		//Añadimos resultados equivalentes que no pueden salir de la lista anterior
		MAP_COD_ESTADO.put("002","PN");
		MAP_COD_ESTADO.put("998","BD");

		//Mapa para busqueda de acciones
		MAP_COD_ACCION.put(1,"Creacion");
		MAP_COD_ACCION.put(2,"Modificacion");
		MAP_COD_ACCION.put(3,"Validado");
		MAP_COD_ACCION.put(4,"Firmado");
		MAP_COD_ACCION.put(5,"Pdte. de Envio");
		MAP_COD_ACCION.put(6,"Exportado a Disco");
		MAP_COD_ACCION.put(7,"Enviado");
		MAP_COD_ACCION.put(8,"Borrada por cliente");
		MAP_COD_ACCION.put(9,"Auditado");
		MAP_COD_ACCION.put(10,"Generar Listado");
		MAP_COD_ACCION.put(11,"Enviado");
		MAP_COD_ACCION.put(12,"Ejecutado");
		MAP_COD_ACCION.put(13,"Borrado Definitivo");
		MAP_COD_ACCION.put(14,"Borrado del Historico");

		// Seateamos los valores de la zona euro.
		LST_ZONA_EURO.add("TTG");
		LST_ZONA_EURO.add("PPG");
		LST_ZONA_EURO.add("NOG");
		LST_ZONA_EURO.add("TIG");
		LST_ZONA_EURO.add("TIF");
		LST_ZONA_EURO.add("TTN");
		LST_ZONA_EURO.add("ACN");
		LST_ZONA_EURO.add("IAN");
		LST_ZONA_EURO.add("PFN");
		LST_ZONA_EURO.add("CND");
		LST_ZONA_EURO.add("CDI");
		LST_ZONA_EURO.add("CDP");
		
		LST_CLASE_INTERNACIONAL.add("TINT");
		LST_CLASE_INTERNACIONAL.add("TINC");
		LST_CLASE_INTERNACIONAL.add("TIN");
		LST_CLASE_INTERNACIONAL.add("TIPT");
		LST_CLASE_INTERNACIONAL.add("TIPC");
		LST_CLASE_INTERNACIONAL.add("TIP");
		
		MAP_CLASE_RED_EXTERIOR.put("NOB","be");
		MAP_CLASE_RED_EXTERIOR.put("PPB","be");
		MAP_CLASE_RED_EXTERIOR.put("TIB","be");
		MAP_CLASE_RED_EXTERIOR.put("TTH","hk");
		MAP_CLASE_RED_EXTERIOR.put("TIH","hk");
		MAP_CLASE_RED_EXTERIOR.put("TTG","gb");
		MAP_CLASE_RED_EXTERIOR.put("PPG","gb");
		MAP_CLASE_RED_EXTERIOR.put("NOG","gb");
		MAP_CLASE_RED_EXTERIOR.put("TIG","gb");
		MAP_CLASE_RED_EXTERIOR.put("PPF","fr");
		MAP_CLASE_RED_EXTERIOR.put("NOF","fr");
		MAP_CLASE_RED_EXTERIOR.put("TTF","fr");
		MAP_CLASE_RED_EXTERIOR.put("TIF","fr");
		MAP_CLASE_RED_EXTERIOR.put("APR","fr");
		MAP_CLASE_RED_EXTERIOR.put("TTN","us");
		MAP_CLASE_RED_EXTERIOR.put("PFN","us");
		MAP_CLASE_RED_EXTERIOR.put("ACN","us");
		MAP_CLASE_RED_EXTERIOR.put("IAN","us");
	}


	/**
	 * Es zona euro.
	 *
	 * @param claseOrden the clase orden
	 * @return true, if successful
	 */
	public static boolean esZonaEuro(final String claseOrden) {
		return !LST_ZONA_EURO.contains(claseOrden);
	}

	/**
	 * Obtiene la sigla correspondiente
	 * al estado que recibe como parametro.
	 *
	 * @param nEstado the n estado
	 * @return the cod sigla
	 */
	public static String getCodSigla(final String nEstado){
		return strDefault(MAP_COD_ESTADO.get(nEstado));
	}

	/**
	 * Obtiene la sigla correspondiente
	 * al estado que recibe como parametro.
	 *
	 * @param nEstado the n estado
	 * @return the cod Estado cod Host
	 */
	public static String getCodEstadoHost(final String nEstado){
		try{
			return "0"+nEstado.substring(0, 3);	//Ejemplo: 011 RECH -> Devuelve 0011
		}catch(IndexOutOfBoundsException e){
			return nEstado;
		}catch(NullPointerException n){
			return nEstado;
		}
	}
	
	/**
	 * Obtiene el numero correspondiente
	 * a la sigla que recibe como parametro.
	 *
	 * @param sEstado the s estado
	 * @return the cod numero
	 */
	public static final String getCodNumero(final String sEstado){
		return strDefault(MAP_ESTADO_COD.get(sEstado));
	}

	/**
	 * Comprueba si el estado pasado es de host o no
	 *
	 * @param sEstado the s estado
	 * @return true or false
	 */
	public static final boolean isEstadoHost(final String sEstado){
		return estadosHost.contains(sEstado);
	}	
	
	/**
	 * Obtiene la accion correspondiente
	 * al estado que recibe como parámetro.
	 *
	 * @param nEstado the n estado
	 * @return the accion
	 */
	public static String getAccion(final int nEstado){
		return strDefault(MAP_COD_ACCION.get(nEstado));
	}

	/**
	 * Comprueba el String y en caso de que sea null devuelve ""
	 * @param str
	 * @return
	 */
	private static String strDefault(final String str){
		return str==null?"":str;
	}


	/**
	 * Devuelve el campo de ordenacion.
	 *
	 * @param campo the campo
	 * @param tipoPeticion the tipo peticion
	 * @return the string
	 */
	public static String getCampoOrden(final String campo, final int tipoPeticion){

		String campoOrden = "";

		//Ordenacion por campos por defecto
		switch(tipoPeticion){
		case ConstantesFO.PET_PENDIENTE:
			if(campo==null || campo.equals("FECR")) {
				campoOrden="TIM_FICHERO";
			} else if(campo.equals("FEPR")) {
				campoOrden="FEC_PROCESCA";
			}
			break;
		case ConstantesFO.PET_CONFECCION:
		case ConstantesFO.PET_HISTORICO:

			if(campo==null || campo.equals("FEPR"))	{
				campoOrden="FEC_PROCESCA";
			}
			break;
		case ConstantesFO.PET_AUDITORIA:
			if(campo==null) {
				campoOrden="F.AUD_FMODIFIC, F.FEC_ACCION2";
			}
			break;
		default:
		}

		if(tipoPeticion!=ConstantesFO.PET_AUDITORIA && campo!=null){
			//Ordenacion por campos que no son los de por defecto
			if(campo.equals("TIOR")) { // Tipo Orden (Campo comun entre tipos de peticion)
				campoOrden="COD_CLASEORD";
			} else if(campo.equals("DIVI")) { // Divisa (Campo comun entre tipos de peticion)
				campoOrden="COD_ABREVIAT";
			} else if(campo.equals("IMPO")) { // Importe (Campo comun entre tipos de peticion)
				campoOrden="QTY_TOTIMP";
			} else if(campo.equals("NOFI")) { // Nombre Fichero (Campo comun entre tipos de peticion)
				campoOrden="DES_NOMFICH";
			} else if(campo.equals("NUOR")) { // Numero Ordenes (Campo comun entre tipos de peticion)
				campoOrden="QNU_TOTREGIS";
			} else if(campo.equals("ESTA")){ // Estado (Campo dependiente segun tipos de peticion)
				if(tipoPeticion==ConstantesFO.PET_PENDIENTE) {
					campoOrden="COD_ESTADODS";
				} else if(tipoPeticion == ConstantesFO.PET_HISTORICO || tipoPeticion == ConstantesFO.PET_CONFECCION) {
					campoOrden="COD_ESTACASH";
				}
			} else if(campo.equals("ASUN")) { // Asunto (Campo dependiente segun tipos de peticion)
				if(tipoPeticion==ConstantesFO.PET_PENDIENTE) {
					campoOrden="DES_ASUNACCE";
				} else if(tipoPeticion == ConstantesFO.PET_HISTORICO || tipoPeticion == ConstantesFO.PET_CONFECCION) {
					campoOrden="DES_CUENORIG";
				}
			}
		}

		return campoOrden;
	}

	public static List<String> convertirFechasTxToBBDD(final List<String> listaFechasTx) throws ParseException{

		final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		final SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS");
		final List<String> listaFechaBBDD = new ArrayList<String>();

		for(String fechaTx:listaFechasTx){
			if(fechaTx.length()>23){
				fechaTx=fechaTx.substring(0,23);
			}
			final Date fechaTxd = sdf2.parse(fechaTx);
			listaFechaBBDD.add(String.valueOf(sdf.format(fechaTxd)));
		}

		return listaFechaBBDD;
	}

	/**
	 * Metodo que convierte la fecha en formato de la bbdd y la convierte en fotmato de TX
	 * @param String fechaBBDD
	 * @return String fechaTX
	 * @throws ParseException
	 */
	public static String convertirFechasBBDDToTx(final String fechaBBDD){

		final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		final SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS");
		String fechaTX = null;
		try{
			final Date fechaTxd = sdf.parse(fechaBBDD);
			fechaTX = String.valueOf(sdf2.format(fechaTxd)).concat("000");
		}catch(final ParseException e){
			fechaTX = fechaBBDD.concat("000");
		}

		return fechaTX;
	}

	public static boolean eqError(final ExcepcionEjecucionAplicacion eea, final CodigoError ce){
		return eea.getCodigoError().toString().equals(ce.toString());
	}

	/**
	 * Comparamos la fecha con null, y operamos segun delta
	 * @param Date fecha
	 * @param int delta
	 * @return Date fecha
	 */
	public static Date addOrsubtractsDate(final Date fecha, final int delta){
		final Date resp;
		if(fecha != null) {
			final Calendar calendar  = Calendar.getInstance();
			calendar.setTime(fecha);
			calendar.add(Calendar.DATE, delta);
			resp = calendar.getTime();
		} else {
			resp = fecha;
		}
		return resp;
	}

	public static List<String> getListaEstadosHostPendientes(){
		return estadosHostPendiente;
	}

	public static String convertirFechasTxToBBDD(String fechaTx) throws ParseException{

		final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		final SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS");
		
			if(fechaTx.length()>23){
				fechaTx=fechaTx.substring(0,23);
			}				
			Date fechaTxd = sdf2.parse(fechaTx);
		
		return String.valueOf(sdf.format(fechaTxd));
	}
	
	/**
	 * Es orden internacional.
	 *
	 * @param claseOrden the clase orden
	 * @return true, if successful
	 */
	public static boolean esClaseInternacional(final String claseOrden) {
		return LST_CLASE_INTERNACIONAL.contains(claseOrden);
	}
	
	/**
	 * Es orden de red exterior.
	 *
	 * @param claseOrden the clase orden
	 * @return true, if successful
	 */
	public static boolean esClaseRedExterior(final String claseOrden) {
		return MAP_CLASE_RED_EXTERIOR.containsKey(claseOrden);
	}
	
	/**
	 * Devuelve el pais de la clase perteneciente a la red exterior.
	 *
	 * @param claseOrden the clase orden
	 * @return true, if successful
	 */
	public static String getPaisClaseRedExterior(final String claseOrden) {
		return MAP_CLASE_RED_EXTERIOR.get(claseOrden);
	}
	
	/**
	 * Retorna la cadena reletiva donde se encuentra el buzon.<br>
	 * Fecha de creación: (10/03/2004 13:02:46)
	 * @return java.lang.String Ruta
	 * @param empresa java.lang.String
	 */
	public static String calcularRutaBuzon(String empresa) throws Exception
	{
		String sRuta = calculaRuta(empresa) + empresa;

		return sRuta;
	}
	
	/**
	 * Retorna la cadena reletiva donde se encuentra el buzon.<br>
	 * Fecha de creación: (10/03/2004 13:02:46)
	 * @return java.lang.String Cadena con la suma del canal, banco y logon de la referencia
	 * @param sLogon java.lang.String
	 */
	public static String calculaRuta(String sLogon)
	{
		int iCanal = (new Integer(sLogon.trim().substring(0,4))).intValue();
		int iBanco = (new Integer(sLogon.trim().substring(4,8))).intValue();
		String sLogonAux = sLogon.trim().substring(8);
		return calculaRuta(iCanal,iBanco,sLogonAux);
	}
	
	/**
	 * Retorna la cadena reletiva donde se encuentra el buzon.<br>
	 * Fecha de creación: (10/03/2004 12:43:45)
	 * @param iCanal int Canal de la referencia
	 * @param iBancoInt int Banco de la referencia
	 * @param sLogon java.lang.String Logon de la referencia
	 * @return java.lang.String
	 */
	public static String calculaRuta(int iCanal, int iBancoInt, String sLogon)
	{
		String sSeparador = System.getProperty("file.separator");
		String sLogAux = sLogon.trim();
		int nTam = sLogAux.length();
		int primerDirDesde = nTam - ConstantesFO.DF_LENG_PRIMERDIR_DESDE;
		int primerDirHasta = nTam - ConstantesFO.DF_LEN_SEGUNDODIR_DESDE;
		int segundoDirDesde = nTam - ConstantesFO.DF_LEN_SEGUNDODIR_DESDE;
//		Cuando se haga la migración se debe quitar el return "", y dejar el otro.
//		return "";
		return (padl(String.valueOf(iCanal),4, '0') + sSeparador + sLogAux.substring(primerDirDesde,primerDirHasta) + sSeparador + sLogAux.substring(segundoDirDesde) + sSeparador);

	}
	
	/**
	 * Devuelve sCadena con el tamaño especificado por iLong, ajustada a
	 * a la derecha y completando los espacios vacios de la izquierda con
	 * el caracter espefificado en sCaracter.
	 *
	 * sCadena: es la cadena que se va a ajustar.
	 * iLong: es la longitud de la cadena que deseamos crear.
	 * sCaracter: es el caracter con el que completar por la izquierda
	 *			  los espacios en blanco.	
	 *	
	*/
	public static String padl(String sCadenaOrigen, int iLongitud, char cCaracter){
		int l_lenOrigen = sCadenaOrigen.length();
		// Número de separadores: Puede resultar ser negativo, si hubiera que truncar sería negativo.
		int l_numSep = iLongitud - l_lenOrigen;
		if (l_numSep <= 0){
			return sCadenaOrigen.substring(l_lenOrigen - iLongitud);
		}else{
			char[] l_buffer = new char[iLongitud];
			java.util.Arrays.fill(l_buffer, 0, l_numSep, cCaracter);
			sCadenaOrigen.getChars(0, l_lenOrigen, l_buffer, l_numSep);
			return new String(l_buffer);
		}
	}	
	
	/**
	 * Busca y reemplaza una serie de caracteres en una cadena.
	 *
	 * sCadenaOrigen: es la cadena en la que se va a buscar.
	 * sCadenaBusqueda: es la serie de caracteres que se van a buscar
	 * sCadenaReemplazo: es la serie de caracteres de reemplazo.
	 *
	*/
	public static String strTran(String sCadenaOrigen, String sCadenaBusqueda, String sCadenaReemplazo)
	{
		String sResultado = "";
		String sAux = "";
		int iPosOcurrencia = 0;
		int iPosReemplazo = 0;
		
		sResultado = sCadenaOrigen;
		sAux = sResultado;
		iPosOcurrencia = sAux.indexOf(sCadenaBusqueda);
		
		while(iPosOcurrencia != -1)
		{
			sAux = sAux.substring(iPosOcurrencia + sCadenaBusqueda.length());
			iPosReemplazo =  sResultado.length() - sAux.length() - sCadenaBusqueda.length();
			sResultado = sResultado.substring(0, iPosReemplazo) + sCadenaReemplazo + sAux; 
			iPosOcurrencia = sAux.indexOf(sCadenaBusqueda);
		}

		return sResultado;
	}
	
	/**
	 * Metodo que devuelve un booleano indicando si es numerico.
	 * Fecha de creación: (07/05/2001 12:51:55)
	 * @return boolean
	 * @param cadena java.lang.String
	 */
	public static boolean esNumerico(String cadena)
	{
		boolean resultado = true;
		
		if(cadena==null)
			return false;

		if(cadena.length()==0)
			return false;
			
		for(int i=0;i<cadena.length() && resultado;i++)
		{
			if(!Character.isDigit(cadena.charAt(i)))
				resultado = false;
		}
		
		return resultado;
	}
	
}
